#ifndef _LS3A5000_
#define _LS3A5000_

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#include "programmer.h"
#include "spi.h"
#include <sys/mman.h>

#define MEM_DEV                     "/dev/mem"
#define SPI_CTRL_REG_BASE             0x1FE001F0
#define DVFS_RESET                    0x420
#define SPI_REG_LENGTH                0x1000

#define ERASE_4         0x20     
#define ERASE_32        0x52 
#define ERASE_64        0xD8
#define ERASE_D7        0xD7
#define ERASE_C4        0xC4
#define ERASE_DB        0xDB
#define ERASE_50        0x50
#define ERASE_81        0x81
#define ERASE_21        0x21
#define ERASE_5C        0x5C
#define ERASE_DC        0xDC

#define REG_SPCR   0x00
#define REG_SPSR   0x01
#define REG_SPDR   0x02
#define REG_SPER   0x03
#define REG_SOFTCS 0x05
#define REG_TIME   0x06
#define REG_PARAM  0x04
#define WREN       0x06
#define WRDI       0x04
#define RDID       0x90
#define RDSR       0x05
#define WRSR       0x01
#define READ       0x03
#define AAI        0x02
#define EBSY       0x70
#define DBSY       0x80
#define EWSR       0x50
#define FAST_READ  0x0B
#define BYTE_WRITE 0x02     /* Byte Program Enable */
#define AAI_WRITE  0xad     /* Byte Program Enable */
#define BE4K       0x20     /* 4K Byte block Rrase, Sector Erase */
#define BE4KSIZE   0x1000   /* 4K Byte block Rrase, Sector Erase */
#define BE32K      0x52     /* 32K Byte block Rrase, Sector Erase */
#define BE32KSIZE  0x8000   /* 32K Byte block Rrase, Sector Erase */
#define BE64K      0xD8     /* 64K Byte block Rrase, Sector Erase */
#define BE64KSIZE  0x10000  /* 64K Byte block Rrase, Sector Erase */
#define CHIPERASE  0xC7     /* Chip Erase */
#define BLKSIZE    0x1000
#define BLKERASE   BE4K
#define MACID_ADDR 0x00
#define DEVID_ADDR 0x01
#define VOID_ADDR  0x00
#define VOID_CMD   0x00
#define CHIPERASESET               0x4
#define CSCCHIPERASET              0x5
#define PROGRAM_AAI_MODE           0x1
#define SPI_FREE                   0x00
#define SPI_BUSY                   0x01

#define CONST     const
#define STATIC    static
#define VOID      void

#define STORE8(Addr, Value)    *(volatile UINT8 *)((Addr)) = ((UINT8) (Value & 0xff))
#define LOAD8(Addr)            *(volatile UINT8 *)((Addr))
#define REGSET(Id,Value)       STORE8(SPI_REG_BASE + Id, Value)
#define REGGET(Id)             LOAD8(SPI_REG_BASE + Id)

typedef off_t     SPI_PHYS_ADDR;
typedef uint8_t   *SPI_VIRT_ADDR;
typedef size_t    MAP_SIZE;
typedef unsigned long long  UINT64;
typedef long long           INT64;
typedef unsigned int        UINT32;
typedef int                 INT32;
typedef unsigned short      UINT16;
typedef unsigned short      CHAR16;
typedef short               INT16;
typedef unsigned char       BOOLEAN;
typedef unsigned char       UINT8;
typedef char                CHAR8;
typedef signed char         INT8;
typedef UINT64              UINTN;
typedef INT64               INTN;

typedef struct _LS3A5000_FLASH_MEMMAP {
  SPI_VIRT_ADDR          spi_ctrl_reg_base_virt;
  SPI_VIRT_ADDR          spi_dvfs_reg_base_virt;
} LS3A5000_FLASH_MEMMAP;

#endif